/* ====================================================================
 * (#)Header: AbstractEntity.java
 * (#)Revision: 
 * (#)Date Created: May 15, 2007 11:56:18 AM
 * (#)Created By: Karol Wozniak
 * ====================================================================
 *
 * Copyright (c) 2007 karolak .  All rights reserved.
 *
 * ====================================================================
 * 
 * The software application represented here is the sole property of 
 * karolak. Its unauthorized utilization is expressly prohibited.
 * 
 * ====================================================================
 */
package com.karolak.entity;

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import javax.persistence.Version;

import com.karolak.bean.BeanUtils;

/**
 * <code>AbstractEntity</code> is used to ....
 * 
 * @author <a href="mailto:kwozniak@hotmail.com">Karol Wozniak</a>
 */
@MappedSuperclass
@EntityListeners(com.karolak.entity.listener.BasicEntityListener.class)
public abstract class AbstractEntity<T> implements Serializable {

	private static final long serialVersionUID = 1L;

	private T id;
	private Integer version;
	private Date createDate;
	private Date updateDate;

	// === get/set === //
	@Transient
	public T getId() {
		return id;
	}

	public void setId(T id) {
		this.id = id;
	}

	@Version
	@Column(name = "obj_version", nullable = false)
	@Basic(fetch = FetchType.EAGER)
	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	@Basic(fetch = FetchType.EAGER)
	@Column(name = "create_date", nullable = false, updatable = false)
	public Date getCreateDate() {
		return createDate;
	}

	public void setCreateDate(Date createDate) {
		this.createDate = createDate;
	}

	@Basic(fetch = FetchType.EAGER)
	@Column(name = "update_date", nullable = true)
	public Date getUpdateDate() {
		return updateDate;
	}

	public void setUpdateDate(Date updateDate) {
		this.updateDate = updateDate;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}

		if (!obj.getClass().isInstance(this)) {
			return false;
		}

		final AbstractEntity<?> entity = (AbstractEntity<?>) obj;
		if (getId() == null || entity.getId() == null) {
			return false;
		}
		return getId().equals(entity.getId());
	}

	/**
	 * TODO consider something better for hashcode ? ref:
	 * http://djeang.blogspot.com
	 * /2005/08/override-equals-and-hashcode-methods.html
	 */
	@Override
	public int hashCode() {
		if (getId() == null) {
			return super.hashCode();
		}
		return getId().hashCode();
	}

	@Override
	public String toString() {
		return BeanUtils.toString(this);
	}
}
